package com.qcxy.gzy.view;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.qcxy.gzy.activity.R;

/**
 * 思路：首先定义最外层小圆点的半径，外层细圆弧的宽度，内存宽圆弧的宽度，两个圆弧中间间隔的宽度，
 * 然后利用旋转画布来绘制文本，接着绘制两个圆弧的底色，接着根据传过来的数据绘制渐变色圆弧和原点 利用ValueAnimator来设置动画效果
 *
 */
public class CircleChartView extends View {

    private static int                           RANGE_FIRST     = 0;
    private static int                           RANGE_TWO       = 30;
    private static int                           RANGE_THREE     = 70;
    private static int                           RANGE_FOUR      = 100;
    /** 画笔 */
    private Paint                                mPaint          = null;
    /** 彩色画笔 */
    private Paint                                mShaderPaint    = null;
    /** 图片画笔 */
    private Paint                                mBitmapPaint    = null;
    /** 文字画笔 */
    private Paint                                mTextPaint      = null;
    /** 控件宽度 */
    private int                                  mWidth;
    /** 控件高度 */
    private int                                  mHeight;
    /** 半径 */
    private int                                  mRadius;
    /** 外圆弧的宽度 */
    private float                                mOuterArcWidth;
    /** 内部大圆弧的宽度 */
    private float                                mInsideArcWidth;
    /** 两圆弧中间间隔距离 */
    private float                                mSpaceWidth;
    /** 最外层滑动小球的半径 */
    private float                                mScrollCircleRadius;

    /** 绿色 */
    private int                                  mGreenColor;
    /** 黄色 */
    private int                                  mYellowColor;
    /** 红色 */
    private int                                  mRedColor;

    /** 灰色 */
    private int                                  mGrayColor;
    /** 自定义的Bitmap */
    private Bitmap                               mBitmap;
    /** 自定义的画布，目的是为了能画出重叠的效果 */
    private Canvas                               mCanvas;
    /** 时刻变化的Angel */
    private double                               mAngel;
    private double                               mMaxAngel;
    /** 内弧半径 */
    private float                                mInsideArcRadius;
    private double                               mAimPercent     = 0;
    private double                               mMaxPercent     = 0;
    private float                                mOuterArcRadius;
    /** 当前点的实际位置 */
    private float[]                              mCurrentPosition;
    /** 当前点的tangent值,用于计算图片所需旋转的角度 */
    private float[]                              mTanValue;
    /** 矩阵,用于对图片进行一些操作 */
    private Matrix                               mMatrix;
    /** 外圈的矩形 */
    private RectF                                mOuterArea;

    /** 字体内容 */
    private String                               mTextContent;
    /** 字体大小 */
    private int                                  mTextSize;

    /** 动效过程监听器 */
    private ValueAnimator.AnimatorUpdateListener mUpdateListener;
    private Animator.AnimatorListener            mAnimatorListener;
    /** 过程动画s */
    private ValueAnimator                        mValueAnimator;
    /** 用于控制动画状态转换 */
    private Handler                              mAnimatorHandler;
    /** 默认的动效周期 2s */
    private int                                  defaultDuration = 2000;

    /** 构造函数 */
    public CircleChartView(Context context) {
        super(context);
        initView(context);

    }

    /** 构造函数 */
    public CircleChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);

    }

    /** 构造函数 */
    public CircleChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);

    }

    /***
     * 初始化操作
     * 
     * @param context
     */
    private void initView(Context context) {
        mShaderPaint = new Paint();
        mTextPaint = new Paint();
        mPaint = new Paint();
        // 设置空心
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);

        mBitmapPaint = new Paint();
        mBitmapPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mBitmapPaint.setAntiAlias(true);

        mOuterArcWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp5);
        mInsideArcWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp48);
        mSpaceWidth = context.getResources().getDimensionPixelOffset(R.dimen.dp33);
        mScrollCircleRadius = context.getResources().getDimensionPixelOffset(R.dimen.distance_4dp);

        mTextSize = context.getResources().getDimensionPixelOffset(R.dimen.sp30);
        mGreenColor = context.getResources().getColor(R.color.percent_green);
        mYellowColor = context.getResources().getColor(R.color.percent_yellow);
        mRedColor = context.getResources().getColor(R.color.percent_red);
        mGrayColor = context.getResources().getColor(R.color.white_color);

        mCurrentPosition = new float[2];
        mTanValue = new float[2];

        mMatrix = new Matrix();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 获取宽度
        mWidth = getWidth();
        // 获取高度
        mHeight = getHeight();
        mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);

        mCanvas = new Canvas(mBitmap);
        // 获取最外圆的半径
        mRadius = mHeight;
        // 内弧半径
        mInsideArcRadius = mRadius - mScrollCircleRadius - mSpaceWidth;

        DrawPercentBackground(mCanvas);
        DrawPercent(mAngel, mMaxAngel, mAimPercent, mMaxPercent, mCanvas);
        paintText(mCanvas);
        canvas.drawBitmap(mBitmap, 0, 0, null);
    }

    /** 画两条线的底色 */
    private void DrawPercentBackground(Canvas canvas) {
        mPaint.setColor(mGrayColor);
        mPaint.setStrokeWidth(mOuterArcWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        // 设置为圆角
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setAntiAlias(true);
        // 绘制外层大宽度弧形
        mOuterArcRadius = mRadius - mOuterArcWidth;
        mOuterArea = new RectF(mWidth / 2 - mOuterArcRadius, mRadius - mOuterArcRadius, mWidth / 2 + mOuterArcRadius, mRadius + mOuterArcRadius);
        canvas.drawArc(mOuterArea, (float) (180), (float) (180), false, mPaint);

        mPaint.setColor(mGrayColor);
        mPaint.setStrokeWidth(mInsideArcWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(new RectF(mWidth / 2 - mInsideArcRadius, mRadius - mInsideArcRadius, mWidth / 2 + mInsideArcRadius, mRadius + mInsideArcRadius), (float) (180), (float) (180), false, mPaint);

    }

    /**
     * 描画百分比
     * 
     * @param percent
     * @param maxPercent
     * @param aimPercent
     * @param maxPercent2
     * @param canvas
     */
    private void DrawPercent(double percent, double maxPercent, double aimPercent, double maxPercent2, Canvas canvas) {
        double roateAngel = percent * 0.01 * 180;
        double roateAngel2 = maxPercent * 0.01 * 180;

        mShaderPaint.setAntiAlias(true);
        mShaderPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        // 圆与圆之间的部分
        if (aimPercent >= RANGE_FIRST && aimPercent <= RANGE_TWO) {
            mShaderPaint.setColor(mGreenColor);
            drawInsideArc((float) (180), (float) roateAngel, canvas);
        } else if (aimPercent > RANGE_TWO && aimPercent <= RANGE_THREE) {
            mShaderPaint.setColor(mYellowColor);
            drawInsideArc((float) (180), (float) (roateAngel), canvas);
            mShaderPaint.setColor(mGreenColor);
            drawInsideArc((float) (180), (float) (54), canvas);
        } else if (aimPercent > RANGE_THREE && aimPercent <= RANGE_FOUR) {
            mShaderPaint.setColor(mRedColor);
            drawInsideArc((float) (180), (float) (roateAngel), canvas);
            mShaderPaint.setColor(mYellowColor);
            drawInsideArc((float) (180), (float) (126), canvas);
            mShaderPaint.setColor(mGreenColor);
            drawInsideArc((float) (180), (float) (54), canvas);
        }
        Log.d("", "------>roateAngel:" + roateAngel);

        // 最大值记录的圆圈
        if (maxPercent2 >= RANGE_FIRST && maxPercent2 <= RANGE_TWO) {
            drawOuterAcr(maxPercent2, (float) (180), (float) roateAngel2, canvas, mYellowColor);
        } else if (maxPercent2 > RANGE_TWO && maxPercent2 <= RANGE_THREE) {
            drawOuterAcr(maxPercent2, (float) (180), (float) (roateAngel2), canvas, mGreenColor);

        } else if (maxPercent2 > RANGE_THREE && maxPercent2 <= RANGE_FOUR) {
            drawOuterAcr(maxPercent2, (float) (180), (float) (roateAngel2), canvas, mRedColor);
        }
        Log.d("", "------>roateAngel2:" + roateAngel2);
    }

    /***
     * 画内部圆环渐变
     * 
     * @param formDegree
     *            起始角度
     * @param toDegree
     *            旋转角度
     * @param canvas
     *            画布
     */
    private void drawInsideArc(float formDegree, float toDegree, Canvas canvas) {
        mShaderPaint.setStrokeWidth(mInsideArcWidth);
        mShaderPaint.setStyle(Paint.Style.STROKE);
        // 内弧半径
        canvas.drawArc(new RectF(mWidth / 2 - mInsideArcRadius, mRadius - mInsideArcRadius, mWidth / 2 + mInsideArcRadius, mRadius + mInsideArcRadius), formDegree, toDegree, false, mShaderPaint);

    }

    /***
     * 绘制外部彩色线条和小红圈 利用PathMeasure的getTranslate测量出需要绘制的圆弧的末端的坐标位置
     * 
     * @param formDegree
     *            起始角度
     * @param toDegree
     *            旋转角度
     * @param canvas
     *            画布
     * @param color
     *            实心颜色
     */
    private void drawOuterAcr(double maxValue, float formDegree, float toDegree, Canvas canvas, int color) {
        mShaderPaint.setStrokeWidth(mOuterArcWidth);
        mShaderPaint.setStyle(Paint.Style.STROKE);
        mShaderPaint.setColor(color);
        Path orbit = new Path();
        // 通过Path类画一个90度（180—270）的内切圆弧路径
        orbit.addArc(mOuterArea, formDegree, toDegree);
        // 创建 PathMeasure
        PathMeasure measure = new PathMeasure(orbit, false);
        measure.getPosTan(measure.getLength(), mCurrentPosition, mTanValue);
        mMatrix.reset();
        // 绘制外层的线条
        canvas.drawPath(orbit, mShaderPaint);
        mBitmapPaint.setColor(color);
        float radious = 6.0f;
        if (maxValue == 0) {
            mCurrentPosition[1] = mCurrentPosition[1] + mHeight;
            radious = 0.0f;
        }
        // 绘制实心小圆圈
        canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], radious, mBitmapPaint);
        mBitmapPaint.setColor(mRedColor);
        float x = mCurrentPosition[0] - 6;
        float y = mCurrentPosition[1] + 20;
        if (maxValue == 0) {
            y = y + mHeight;
        }
        mBitmapPaint.setTextSize(16.0f);
        canvas.drawText(String.valueOf((int) maxValue), x, y, mBitmapPaint);
    }

    /**
     * 描画字体
     * 
     * @param canvas
     */
    private void paintText(Canvas canvas) {
        if (!TextUtils.isEmpty(mTextContent)) {
            if (mAimPercent >= RANGE_FIRST && mAimPercent <= RANGE_TWO) {
                mTextPaint.setColor(mYellowColor);
            } else if (mAimPercent > RANGE_TWO && mAimPercent <= RANGE_THREE) {
                mTextPaint.setColor(mGreenColor);
            } else if (mAimPercent > RANGE_THREE && mAimPercent <= RANGE_FOUR) {
                mTextPaint.setColor(mRedColor);
            }
            mTextPaint.setTextSize(mTextSize);
            mTextPaint.setTextAlign(Paint.Align.CENTER);
            mTextPaint.setStrokeWidth(2);
            canvas.drawText(mTextContent, mWidth / 2, mRadius - mTextSize / 2, mTextPaint);
        }
    }

    /**
     * 设置角度变化，刷新界面
     * 
     * @param aimPercent
     *            目标百分比
     */
    public void setPercent(double aimPercent, double maxPercent) {

        // 两边监测
        if (aimPercent < 0) {
            aimPercent = 0;
        } else if (aimPercent > 100) {
            aimPercent = 100;
        }

        if (maxPercent < 0) {
            maxPercent = 0;
        } else if (maxPercent > 100) {
            maxPercent = 100;
        }
        this.mAimPercent = aimPercent;
        this.mMaxPercent = maxPercent;

        initListener();
        initHandler();
        initAnimator();
        mValueAnimator.start();

    }

    /**
     * 设置文字
     * 
     * @param
     * @param textContent
     *            百分比
     */
    public void setText(String textContent) {
        this.mTextContent = textContent;
        mAnimatorHandler.sendEmptyMessage(1);

    }

    private void initListener() {
        mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAngel = mAimPercent;
                mMaxAngel = mMaxPercent;
                invalidate();
            }
        };

        mAnimatorListener = new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // getHandle发消息通知动画状态更新
                mAnimatorHandler.sendEmptyMessage(0);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        };
    }

    private void initHandler() {
        mAnimatorHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 0:
                        mValueAnimator.removeAllUpdateListeners();
                        mValueAnimator.removeAllListeners();
                        break;
                    case 1:
                        invalidate();
                        break;
                }

            }
        };
    }

    private void initAnimator() {
        mValueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(defaultDuration);

        mValueAnimator.addUpdateListener(mUpdateListener);

        mValueAnimator.addListener(mAnimatorListener);
    }

}